---
title: 'Preprocessors API in Node Events'
description: 'Prepare support and spec files for the browser with preprocessors.'
sidebar_label: 'Preprocessors API'
---

<ProductHeading product="app" />

# Preprocessors API

A preprocessor is the plugin responsible for preparing a
[support file](/app/core-concepts/writing-and-organizing-tests#Support-file)
or a [spec file](/app/core-concepts/writing-and-organizing-tests#Spec-files)
for the browser.

A preprocessor could transpile your file from another language (CoffeeScript or
ClojureScript) or from a newer version of JavaScript (ES2017).

A preprocessor also typically watches the source files for changes, processes
them again, and then notifies Cypress to re-run the tests.

## Examples

We've created three preprocessors as examples for you to look at. These are
fully functioning preprocessors.

The code contains comments that explain how it utilizes the preprocessor API.

- [webpack preprocessor](https://github.com/cypress-io/cypress/tree/develop/npm/webpack-preprocessor)
- [Browserify preprocessor](https://github.com/cypress-io/cypress-browserify-preprocessor)
- [Watch preprocessor](https://github.com/cypress-io/cypress-watch-preprocessor)

## Defaults

By default, Cypress comes packaged with the **webpack preprocessor** already
installed.

The webpack preprocessor handles:

- ES2015 and JSX via Babel
- TypeScript
- CoffeeScript `1.x.x`
- Watching and caching files

:::info

Are you looking to change the **default options** for webpack?

:::

If you already use webpack in your project, you can pass in your webpack config
as
[shown here](https://github.com/cypress-io/cypress/tree/develop/npm/webpack-preprocessor#options).

If you don't use webpack in your project or would like to keep the majority of
the default options, you can
[modify the default options](https://github.com/cypress-io/cypress/tree/develop/npm/webpack-preprocessor#modifying-default-options).
Editing the options allows you to do things like:

- Add your own Babel plugins
- Modify options for TypeScript compilation
- Add support for CoffeeScript `2.x.x`

## Usage

<WarningSetupNodeEvents />

To use a preprocessor, you should bind to the `file:preprocessor` event in your
[setupNodeEvents](/app/plugins/plugins-guide#Using-a-plugin) function:

:::cypress-config-plugin-example

```javascript
on('file:preprocessor', (file) => {
  // ...
})
```

:::

### The callback function should return one of the following:

- A promise\* that eventually resolves the path to the **built file**\*\*.
- A promise\* that eventually rejects with an error that occurred during
  processing.

:::note

\* The promise should resolve only after the file has completed writing to disk.
The promise resolving is a signal that the file is ready to be served to the
browser.

:::

---

:::note

\*\* The built file is the file that is created by the preprocessor that will
eventually be served to the browser.

:::

:::note

If, for example, the source file is `spec.coffee`, the preprocessor should:

:::

1. Compile the CoffeeScript into JavaScript `spec.js`
2. Write that JavaScript file to disk (example: `/Users/foo/tmp/spec.js`)
3. Resolve with the absolute path to that file: `/Users/foo/tmp/spec.js`

:::caution

This callback function can and _will_ be called multiple times with the same
`filePath`.

The callback function is called any time a file is requested by the browser.
This happens on each run of the tests.

Make sure not to start a new watcher each time it is called. Instead, cache the
watcher and, on subsequent calls, return a promise that resolves when the latest
version of the file has been processed.

:::

## File object

The `file` object passed to the callback function has the following properties:

| Property      | Description                                                                                                                                                                                                                       |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `filePath`    | The full path to the source file.                                                                                                                                                                                                 |
| `outputPath`  | The suggested path for saving the preprocessed file to disk. This is unique to the source file. A preprocessor can choose to write the file elsewhere, but Cypress automatically provides you this value as a convenient default. |
| `shouldWatch` | A boolean indicating whether the preprocessor should watch for file changes or not.                                                                                                                                               |

## File events

The `file` object passed to the callback function is an
[Event Emitter](https://nodejs.org/api/events.html#events_class_eventemitter).

### Receiving 'close' event

When the running spec, the project, or the browser is closed while running
tests, the `close` event will be emitted. The preprocessor should do any
necessary cleanup in this function, like closing the watcher when watching.

```javascript
// example
const watcher = fs.watch(filePath /* ... */)

file.on('close', () => {
  watcher.close()
})
```

### Sending 'rerun' event

If watching for file changes, emit `rerun` after a file has finished being
processed to let Cypress know to rerun the tests.

```javascript
// example
fs.watch(filePath, () => {
  file.emit('rerun')
})
```

## Source maps

<SourceMaps />

## Publishing

Publish preprocessors to [npm](https://www.npmjs.com/) with the naming
convention `cypress-*-preprocessor` (e.g. cypress-clojurescript-preprocessor).

Use the following npm keywords:

```json
"keywords": [
  "cypress",
  "cypress-plugin",
  "cypress-preprocessor"
]
```

Feel free to submit your published plugins to our [list of plugins](/app/plugins/plugins-list).
